﻿using BaseAuthRole.AspNetCore.Client;
using BaseAuthRole.Domain.Input;
using BaseAuthRole.Domain.OutPut;
using log4net;
using Newtonsoft.Json;
using RS.BaseModel.Common;
using RS.Tool.Base;
using RS.Tool.DataBase;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace BaseAuthRole.AspNetCore
{
    public class BaseAuthClient : IBaseAuthClient
    {
        private BaseAuthOption _baseAuthOption;

        private string GetAppAccessTokenApiName = "/api/Gateway/GetAppAccessToken";

        private string GetBaseAuthConfigApiName = "/api/Gateway/GetBaseAuthConfig";

        private string CheckAppAccessTokenApiName = "/api/Gateway/CheckAppAccessToken";

        private string GetUserAuthTokenApiName = "/api/Gateway/GetUserAuthToken";
        private string GetUserInfoApiName = "/api/Gateway/GetUserInfo";

        private string GetUserDetailInfoApiName = "/api/Gateway/GetUserDetailInfo";

        private string GetUserInfoListApiName = "/api/Gateway/GetUserInfoList";

        private string GetSimpleUserInfoListApiName = "/api/Gateway/GetSimpleUserInfoList";

        private string GetUserInfoByUidApiName = "/api/Gateway/GetUserInfoByUid";

        private string GetUserInfoByJobNumberApiName = "/api/Gateway/GetUserInfoByJobNumber";

        private string GetUserInfoByLoginNameApiName = "/api/Gateway/GetUserInfoByLoginName";

        private string GetOrgIdListByOrgIdApiName = "/api/Gateway/GetOrgIdListByOrgId";

        private string GetSubOrgIdListByOrgIdApiName = "/api/Gateway/GetSubOrgIdListByOrgId";

        private string GetAllSimpleOrgListApiName = "/api/Gateway/GetAllSimpleOrgList";

        private string GetOrgInfoByOrgIdApiName = "/api/Gateway/GetOrgInfoByOrgId";

        private string GetOrgInfosByOrgIdsApiName = "/api/Gateway/GetOrgInfosByOrgIds";

        private string GetKnowledgeAuthInfoListApiName = "/api/Gateway/GetKnowledgeAuthInfoList";

        private string UpdateKnowledgeReadActionApiName = "/api/Gateway/UpdateKnowledgeReadAction";

        private string GetKnowledgeAuthOrganizationListApiName = "/api/Gateway/GetKnowledgeAuthOrganizationList";

        private static CacheHelper CacheHelper = new CacheHelper();

        private static ILog logger = log4net.LogManager.GetLogger("BaseAuthClient");

        private string _appAccessTokenKey;
        public BaseAuthClient(BaseAuthOption baseAuthOption)
        {
            _baseAuthOption = baseAuthOption;
            _appAccessTokenKey = $"{_baseAuthOption.AppId}_appAccessToken";

            //校验配置并获取accesstoken
           this.GetAppAccessToken();

        }

        public string GetAppAccessTokenFromCache() {

            var appAccessToken = CacheHelper.Get<string>(_appAccessTokenKey);

            if (string.IsNullOrEmpty(appAccessToken)) {

                appAccessToken=this.GetAppAccessToken().Result.AppAccessToken;
            }

            return appAccessToken;

        }

        public T ApiGet<T>(string apiName, string paraStr)
        {

            var url = $"{_baseAuthOption.AuthDomain}{apiName}";

            if (!string.IsNullOrEmpty(paraStr))
            {

                url = url + "?" + paraStr;
            }

            //logger.Info(url);

            var resutlStr = HttpHelper.Get(url);

            if (string.IsNullOrEmpty(resutlStr))
            {
                throw new Exception("接口请求结果为空");
            }
            else
            {
                var result = JsonConvert.DeserializeObject<T>(resutlStr);

                return result;
            }



        }

        public T ApiGet<T>(string apiName, object paraObject)
        {

            var url = $"{_baseAuthOption.AuthDomain}{apiName}";


            var paraStr = "";
            if (paraObject != null) {
              
                var t = paraObject.GetType();
                
                var pros=t.GetProperties();

                foreach (var o in pros) {

                    var name = o.Name;

                    var value = "";

                    var valueObj= o.GetValue(paraObject);

                    if (o.PropertyType.Name == "List`1")
                    {

                        if (valueObj != null)
                        {
                            var temp = (List<string>)valueObj;

                            foreach (var p in temp)
                            {

                                if (p != null)
                                {
                                    paraStr += $"{name}={p}&";
                                }

                            };
                        }
                    }
                    else
                    {
                        if (valueObj != null)
                        {
                            value = valueObj.ToString();                           
                        }
                        paraStr += $"{name}={value}&";
                    }
                   
                }

                if (!string.IsNullOrEmpty(paraStr)) {

                    paraStr = paraStr.Substring(0,paraStr.Length-1);

                    paraStr = $"{paraStr}";
                }                                    
            }
            return this.ApiGet<T>(apiName, paraStr);
        }

        public T ApiPost<T>(string apiName, object paraObject)
        {

            var url = $"{_baseAuthOption.AuthDomain}{apiName}";

            logger.Info(JsonConvert.SerializeObject(paraObject));
            try
            {


                var resultStr = HttpHelper.Post(url, JsonConvert.SerializeObject(paraObject));

                if (string.IsNullOrEmpty(resultStr))
                {
                    throw new Exception("接口请求结果为空");
                }
                else
                {
                    var result = JsonConvert.DeserializeObject<T>(resultStr);

                    return result;
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message);
                throw new Exception("接口请求结果为空");
            }

        }

        /// <summary>
        /// 没有回调地址的，登录后调回Home页
        /// </summary>
        /// <param name="redirectUri"></param>
        /// <param name="scope"></param>
        /// <returns></returns>
        public string BuildAuthUrl(string redirectUri, string scope = "auth_base")
        {

            if (string.IsNullOrEmpty(redirectUri))
            {
                redirectUri = _baseAuthOption.HomeUrl;
            }

            var RedirectUri = _baseAuthOption.AuthCodeUrl + $"?return_url={HttpUtility.UrlEncode(redirectUri)}";

            var url = this._baseAuthOption.AuthDomain + $"/OAuth2/PublicAppAuthorize?AppId={_baseAuthOption.AppId}&Scope={scope}&RedirectUri={HttpUtility.UrlEncode(RedirectUri)}";

            return url;

        }

        #region Api

        /// <summary>
        /// 判断用户是否登录
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [Obsolete]
        public CommonResult<GetUserInfoOutPut> IfUserLogined(string token)
        {

            var result=new CommonResult<GetUserInfoOutPut>();

            if (string.IsNullOrEmpty(token))
            {
                result.Value = RS.BaseModel.Enum.EnumBaseResult.KeyParaMiss;

                return result;
            }             

            var r = this.ApiGet<CommonResult<GetUserInfoOutPut>>(GetUserInfoApiName, $"appid={_baseAuthOption.AppId}&appaccesstoken={this.GetAppAccessTokenFromCache()}&AuthToken={token}");

            return r;

        }

       /// <summary>
        /// 获取appaccesstoken
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public CommonResult<GetAppAccessTokenModelOutPut> GetAppAccessToken()
        {

           
            var r_accesstoken = this.ApiGet<CommonResult<GetAppAccessTokenModelOutPut>>(GetAppAccessTokenApiName,$"appid={_baseAuthOption.AppId}&secret={_baseAuthOption.Secret}");

            if (!r_accesstoken.IsError)
            {
                CacheHelper.Set(_appAccessTokenKey, r_accesstoken.Result.AppAccessToken, r_accesstoken.Result.ExpireTime);
            }
            else {

                throw new Exception(r_accesstoken.Message);
                                       
             };

            return r_accesstoken;

        }


        public CommonResult<GetUserAuthTokenOutput> GetAuthToken(string code) { 
        
            var r=new CommonResult<GetUserAuthTokenOutput>();

            var input = new GetUserAuthTokenInput
            {
                 AppAccessToken=this.GetAppAccessTokenFromCache(),
                 AppId=_baseAuthOption.AppId,
                  AuthCode=code,

            };

            var info = this.ApiGet<CommonResult<GetUserAuthTokenOutput>>(GetUserAuthTokenApiName, input);


            return info;

        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        public CommonResult<GetUserInfoOutPut> GetUserInfo(string auth_token) {

            var result = new CommonResult<GetUserInfoOutPut>();

            var input = new GetUserInfoInput
            {
                 AppId= _baseAuthOption.AppId,
                 AppAccessToken=this.GetAppAccessTokenFromCache(),
                 AuthToken= auth_token
            };

            var info = this.ApiGet<CommonResult<GetUserInfoOutPut>>(GetUserInfoApiName,input);


            return info;

        }

        public CommonResult<GetUserDetailInfoOutPut> GetUserDetailInfo(string auth_token)
        {
            var result = new CommonResult<GetUserDetailInfoOutPut>();

            var input = new GetUserInfoInput
            {
                AppId= _baseAuthOption.AppId,
                AppAccessToken=this.GetAppAccessTokenFromCache(),
                AuthToken= auth_token
            };

            var info = this.ApiGet<CommonResult<GetUserDetailInfoOutPut>>(GetUserDetailInfoApiName, input);


            return info;
        }

        public CommonResult<GetUserInfoOutPut> GetUserInfoByUid(string uid)
        {

            var result = new CommonResult<GetUserInfoOutPut>();

            var input = new GetUserInfoByUidInput
            {
                AppId = _baseAuthOption.AppId,
                AppAccessToken = this.GetAppAccessTokenFromCache(),
                Uid=uid
            };

            var info = this.ApiGet<CommonResult<GetUserInfoOutPut>>(GetUserInfoByUidApiName, input);

            return info;

        }

        public CommonResult<GetUserInfoOutPut> GetUserInfoByJobNum(string JobNum)
        {

            var result = new CommonResult<GetUserInfoOutPut>();

            var input = new GetUserInfoByJobNumberInput
            {
                AppId = _baseAuthOption.AppId,
                AppAccessToken = this.GetAppAccessTokenFromCache(),
                JobNumber=JobNum                
            };

            var info = this.ApiGet<CommonResult<GetUserInfoOutPut>>(GetUserInfoByJobNumberApiName, input);

            return info;

        }

        public CommonResult<GetUserInfoOutPut> GetUserInfoByLoginName(string LoginName)
        {
            var result = new CommonResult<GetUserInfoOutPut>();

            var input = new GetUserInfoByLoginNameInput
            {
                AppId = _baseAuthOption.AppId,
                AppAccessToken = this.GetAppAccessTokenFromCache(),
                LoginName=LoginName
            };

            var info = this.ApiGet<CommonResult<GetUserInfoOutPut>>(GetUserInfoByLoginNameApiName, input);

            return info;
        }

        public CommonResult<PageModel<GetUserInfoOutPut>> GetUserInfoList(GetUserInfoListInput input) {

            var result = new CommonResult<PageModel<GetUserInfoOutPut>>();

            input.AppId = _baseAuthOption.AppId;
            input.AppAccessToken= this.GetAppAccessTokenFromCache();

            var info = this.ApiGet<CommonResult<PageModel<GetUserInfoOutPut>>>(GetUserInfoListApiName, input);


            return info;

        }

        public CommonResult<PageModel<GetSimpleUserInfoOutPut>> GetSimpleUserInfoList(GetUserInfoListInput input)
        {

            var result = new CommonResult<PageModel<GetSimpleUserInfoOutPut>>();

            input.AppId = _baseAuthOption.AppId;
            input.AppAccessToken= this.GetAppAccessTokenFromCache();

            var info = this.ApiGet<CommonResult<PageModel<GetSimpleUserInfoOutPut>>>(GetSimpleUserInfoListApiName, input);


            return info;

        }

        /// <summary>
        /// 应用授权验证
        /// </summary>
        /// <param name="appid"></param>
        /// <param name="appaccesstoken"></param>
        /// <returns></returns>
        public CommonResult CheckAppAccessToken(string appid,string appaccesstoken) {

            var info = this.ApiGet<CommonResult>(CheckAppAccessTokenApiName, $"appid={appid}&appaccesstoken={appaccesstoken}");

            return info;
        }

        public CommonResult<List<string?>> GetOrgIdListByOrgId(GetOrgIdListByOrgIdInput input)
        {
            var result = new CommonResult<List<string?>>();

            var info = this.ApiGet<CommonResult<List<string?>>>(GetOrgIdListByOrgIdApiName, input);

            return info;
        }

        public CommonResult<List<string?>> GetSubOrgIdListByOrgId(GetOrgIdListByOrgIdInput input)
        {
            var result = new CommonResult<List<string?>>();

            var info = this.ApiGet<CommonResult<List<string?>>>(GetSubOrgIdListByOrgIdApiName, input);

            return info;
        }

        public CommonResult<List<SimpleOrgOutput>> GetAllSimpleOrgList()
        {
            var result = new CommonResult<List<SimpleOrgOutput>>();

            var info = this.ApiGet<CommonResult<List<SimpleOrgOutput>>>(GetAllSimpleOrgListApiName, "");

            return info;
        }

        public CommonResult<OrgOutPut?> GetOrgInfoByOrgId(GetOrgInfoByOrgIdInput input)
        {
            var result = new CommonResult<OrgOutPut?>();

            var info = this.ApiGet<CommonResult<OrgOutPut?>>(GetOrgInfoByOrgIdApiName, input);

            return info;
        }

        public CommonResult<List<OrgOutPut>?> GetOrgInfosByOrgIds(GetOrgInfosByOrgIdsInput input)
        {
            var info = this.ApiGet<CommonResult<List<OrgOutPut>?>>(GetOrgInfosByOrgIdsApiName, input);
            return info;
        }

        public CommonResult<List<KnowledgeAuthOutPut>?> GetKnowledgeAuthInfoList(GetKnowledgeAuthInfoListInput input)
        {
            var info = this.ApiGet<CommonResult<List<KnowledgeAuthOutPut>?>>(GetKnowledgeAuthInfoListApiName, input);
            return info;
        }

        public CommonResult UpdateKnowledgeReadAction(UpdateKnowledgeReadActionInput input)
        {
            input.OriActionName = HttpUtility.UrlEncode(input.OriActionName);
            input.ActionName = HttpUtility.UrlEncode(input.ActionName);
            input.ControlName = HttpUtility.UrlEncode(input.ControlName);
            input.Description = HttpUtility.UrlEncode(input.Description);

            var info = this.ApiGet<CommonResult>(UpdateKnowledgeReadActionApiName, input);
            return info;
        }

        public CommonResult<GetKnowledgeAuthOrganizationApiListOut?> GetKnowledgeAuthOrganizationApiList(GetKnowledgeAuthOrganizationApiListInput input)
        {
            var info = this.ApiGet<CommonResult<GetKnowledgeAuthOrganizationApiListOut>?>(GetKnowledgeAuthOrganizationListApiName, input);
            return info;
        }

        #endregion
    }
}
